#include <sstream>
#include <iomanip>
#include <QtDebug>
#include <QFileDialog>
#include <QMessageBox>
#include "FakeJtag.h"
#include "ui_fakejtag.h"
#include "Emboard.h"

using namespace etb;

extern "C" void ARM9DASM(unsigned int, char *);

FakeJtag::FakeJtag(QWidget *parent) : QDialog(parent), ui(new Ui::FakeJtag), board_(NULL)
{
  ui->setupUi(this);

  connect(ui->BrowseSaveToolButton, SIGNAL(clicked()), this, SLOT(saveAct()));
  connect(ui->BrowseDownToolButton, SIGNAL(clicked()), this, SLOT(loadAct()));
  connect(ui->ProgToolButton, SIGNAL(clicked()), this, SLOT(programButton()));
  connect(ui->DumpToolButton, SIGNAL(clicked()), this, SLOT(dumpButton()));

  connect(ui->StepPushButton, SIGNAL(clicked()), this, SLOT(stepRunButton()));
  connect(ui->StopPushButton,SIGNAL(clicked()), this, SLOT(stopButton()));

  connect(ui->EraseRadioButton, SIGNAL(click()), this, SLOT(setProgLayout()));
  //set background color
  ui->JtagStatusLineEdit->setStyleSheet("background-color: rgb(0, 255, 0)");
  //ui->JtagLineEdit->setStyleSheet("background:green");
  //this->setFixedSize();
  setFixedSize(360,330);
}

void FakeJtag::loadAct()
{
  QString fileName = QFileDialog::getOpenFileName(ui->BrowseDownToolButton, tr("Open File"),
                          QDir::currentPath());

  ui->FilePathLineEdit->setText(fileName);
}

void FakeJtag::saveAct()
{
  QString path = QDir::currentPath() + "/untitled.txt";
  QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
               path);

  ui->FileSaveLineEdit->setText(fileName);
  if (ui->DumpNorRadioButton->isChecked())
  {
    qDebug() << "DumpNorRadioButton";
  }

  if (ui->DumpSdramRadioButton->isChecked())
  {
     qDebug() << "DumpSdramRadioButton";
  }
  //TODO: filename write or not
  bool success = true;
  if (success)
  {

  }
  else
  {
    QMessageBox::information(this, "Error Saving File",
                 "Could not save the file");
  }
}

void FakeJtag::showCpuInfo()
{
  std::vector<U32> regs;
  board_->jtagGetCpuState(regs);

  int n = 0;
  for (std::vector<U32>::const_iterator i = regs.begin();
      i != regs.end(); i++) {
    std::cout << "R" << std::dec << n << ": 0x" << std::hex << *i << " ";
    n++;    
  }

  std::ostringstream oss;

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[0];
  ui->R0LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[1];
  ui->R1LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[2];
  ui->R2LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[3];
  ui->R3LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[4];
  ui->R4LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[5];
  ui->R5LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[6];
  ui->R6LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[7];
  ui->R7LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[8];
  ui->R8LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[9];
  ui->R9LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[10];
  ui->R10LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[11];
  ui->R11LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[12];
  ui->R12LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[13];
  ui->R13LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[14];
  ui->R14LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[15];
  ui->R15LineEdit->setText(oss.str().c_str());
  oss.str("");

  oss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << regs[16];
  ui->CpLineEdit->setText(oss.str().c_str());
  oss.str("");

  //U32 jtagGetInstruction();
  //U8 jtagGetMachineState() { return state_; }
  U32 instr = board_->jtagGetInstruction();
  U8 status = board_->jtagGetMachineState();

  std::cout << "machine status: " << status << std::endl;
  char str[128]={0};
  ARM9DASM(instr, str);

  std::cout << "0x" << std::hex << regs[15] << ": " <<
    "0x" << instr << " - " << str << std::endl;;

}

void FakeJtag::programButton()
{
  if (ui->EraseRadioButton->isChecked())
  {
    qDebug() << "EraseRadioButton";
//    ui->FilePathLineEdit->setVisible(false);
//    ui->BrowseDownToolButton->setVisible(false);
//    ui->FileDownLabel->setVisible(false);
    for (int i = 0; i < 2048; ++i) {
       U8 buf[1024];
       memset(buf, 0x0, sizeof(buf));

       board_->jtagDownloadBinary(Emboard::DOWNLOAD_TO_NOR, (U8*)buf, 1024 * i, 1024);
     }

     QMessageBox::information(this, "Erase Info", "Erase NOR flash complete!");
     return;
  }

  QString fileName = ui->FilePathLineEdit->text();
  QFile file(fileName);
  bool success = file.open(QIODevice::ReadOnly);
  if (success)
  {
    int size = file.size();
    qDebug()<< "file size= " << size;

    U8 downMode = Emboard::DOWNLOAD_TO_NOR;
    if (ui->SdramRadioButton->isChecked())
      downMode = Emboard::DOWNLOAD_TO_SDRAM;
    else if (ui->NorFlashRadioButton->isChecked())
      downMode = Emboard::DOWNLOAD_TO_NOR;
    else
      downMode = Emboard::DOWNLOAD_TO_NOR;

    ui->DownLoadProgressBar->setTextVisible(true);
    ui->DownLoadProgressBar->setRange(0, size);

    qint64 n = 0;
    qint64 pos = 0;
    do {
      char buf[128];
      n = file.read(buf, 128);
      //std::cout << "read size = " << n << std::endl;
      if (n > 0)
      board_->jtagDownloadBinary(downMode, (U8*)buf, pos, n);
      pos += n;
      //std::cout << "pos = " << pos << std::endl;

      ui->DownLoadProgressBar->setValue(pos);
    } while (n > 0);

    file.close();

    QMessageBox::information(this, "Download Info", "Download file complete!");
    if (downMode == Emboard::DOWNLOAD_TO_SDRAM)
      board_->jtagSetPc(0x30000000);
  }
  else
  {
    QMessageBox::information(this, "Error Opening File",
                 "Could not open File");
  }
}

void FakeJtag::dumpButton()
{


}

void FakeJtag::stepRunButton()
{
  if (board_->jtagStepRunMachine())
    showCpuInfo();
}

void FakeJtag::stopButton()
{
  if (ui->StopPushButton->text()== tr("Pause"))
  {
    board_->jtagPauseMachine();
    showCpuInfo();
    ui->StopPushButton->setText(tr("Run"));
  }
  else if(ui->StopPushButton->text()== tr("Run"))
  {
    board_->jtagContinueMachine();
    ui->StopPushButton->setText(tr("Pause"));
  }
}

 void FakeJtag::setProgLayout()
 {
   if (ui->EraseRadioButton->isChecked())
   {
     //qDebug() << "EraseRadioButton";
     ui->FilePathLineEdit->setVisible(false);
     ui->BrowseDownToolButton->setVisible(false);
     ui->FileDownLabel->setVisible(false);
   }
 }

FakeJtag::~FakeJtag()
{
  delete ui;
}

